package com.longway.common.service;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.ICallback;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Table;
import com.jfinal.plugin.activerecord.TableMapping;
import com.longway.common.db.id.IIdFactory;
import com.longway.common.db.id.IdManager;
import com.longway.common.db.id.MysqlIdFactory;
import com.longway.common.db.id.OracleSeqIdFactory;

public class BaseService {

	protected Object getId(){
		return IdManager.me().getIdFactory("second").getId();
	}
	
	@SuppressWarnings("rawtypes")
	protected String getPK(Class<? extends Model> modelClass) {
		return _getTable(modelClass).getPrimaryKey()[0];		
	}
	
	@SuppressWarnings("rawtypes")
	protected Table _getTable(Class<? extends Model> modelClass) {
		return TableMapping.me().getTable(modelClass);
	}
	
	protected boolean save(Model<?> entity){
		Object id = IdManager.me().getDefaultIdFactory().getId();
		if(entity.get(getPK(entity.getClass()))==null){
			entity.set(getPK(entity.getClass()),id);		
		};
		return entity.save();
	}
	
	public  int[] batchSave(List<? extends Model> modelList, int batchSize){
		IIdFactory ify = IdManager.me().getDefaultIdFactory();
		if(ify instanceof MysqlIdFactory){
			for(Model model : modelList){
				Object id = ify.getId();
				if(model.get(getPK(model.getClass()))==null){
					model.set(getPK(model.getClass()),id);		
				};
			}
		}
		return Db.batchSave(modelList, batchSize);
	}
	
	public  int[] batchUpdate(List<? extends Model> modelList, int batchSize){
		return Db.batchUpdate(modelList, batchSize);
	}
	
	protected  String getPlaceholderSql(Object ... params){
		StringBuilder sql = new StringBuilder("(");
		for(Object param : params){
			sql.append("?,");
		}
		String plc = sql.toString();
		plc = plc.substring(0, plc.length()-1)+")";
		return plc;
	}
	
	protected boolean callPro(String callName ,ProCallback proCallback) {
	    Boolean flag = false;
	    Object o = Db.execute(new ICallback() {
	        @Override
	        public Boolean call(Connection conn) throws SQLException {
	            Boolean flag = false;
	            try {
	                CallableStatement proc = conn.prepareCall("{CALL "+callName+"}");
	                proCallback.setInParams(proc);
	                proCallback.setOutParams(proc);
	                proc.execute();
	                proCallback.getResult(proc);
	                //代码来到这里就说明你的存储过程已经调用成功，如果有输出参数，接下来就是取输出参数的一个过程
	                flag = true;
	            } catch (Exception e) {
	                e.printStackTrace();
	            }
	            return flag;
	        }
	    });
	    flag = (Boolean) o;
	    return flag;
	}	
	
    private interface ProCallback{
        public void setInParams(CallableStatement cst);
        public void setOutParams(CallableStatement cst);
        public Object getResult(CallableStatement cst);
    };
}
